/**
 * <copyright>
 * </copyright>
 *
 * $Id$
 */
package gsoc.ogsadai.model.provider;

import gsoc.ogsadai.client.ServerClient;
import gsoc.ogsadai.model.ActivityType;
import gsoc.ogsadai.model.ModelFactory;
import gsoc.ogsadai.model.ModelPackage;
import gsoc.ogsadai.model.PipelineType;
import gsoc.ogsadai.model.RequestType;
import gsoc.ogsadai.model.WorkflowType;

import java.net.MalformedURLException;
import java.sql.ResultSet;
import java.text.BreakIterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.ResourceLocator;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.provider.ComposeableAdapterFactory;
import org.eclipse.emf.edit.provider.IEditingDomainItemProvider;
import org.eclipse.emf.edit.provider.IItemLabelProvider;
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
import org.eclipse.emf.edit.provider.IItemPropertySource;
import org.eclipse.emf.edit.provider.IStructuredItemContentProvider;
import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
import org.eclipse.emf.edit.provider.ItemPropertyDescriptor;
import org.eclipse.emf.edit.provider.ItemProviderAdapter;
import org.eclipse.emf.edit.provider.ViewerNotification;
import org.eclipse.emf.transaction.TransactionalEditingDomain;

import uk.org.ogsadai.client.toolkit.exception.ResourceUnknownException;
import gsoc.ogsadai.model.properties.PropertiesFactory;
import gsoc.ogsadai.model.properties.PropertiesPackage;
import gsoc.ogsadai.model.properties.PropertiesStyle;
import gsoc.ogsadai.model.properties.provider.PropertiesStyleItemProvider;
import org.eclipse.gmf.runtime.emf.core.GMFEditingDomainFactory;
import org.opensaml.MalformedException;

/**
 * This is the item provider adapter for a {@link gsoc.ogsadai.model.ActivityType} object.
 * <!-- begin-user-doc --> <!--
 * end-user-doc -->
 * @generated
 */
public class ActivityTypeItemProvider extends ItemProviderAdapter implements
		IEditingDomainItemProvider, IStructuredItemContentProvider,
		ITreeItemContentProvider, IItemLabelProvider, IItemPropertySource {

	private String resourceType;
	protected Adapter resourceAdapter = new AdapterImpl() {
		public void notifyChanged(Notification notification) {
			if (notification.getFeatureID(ActivityType.class) == ModelPackage.ACTIVITY_TYPE__RESOURCE) {
				if (notification.getNewStringValue()!= null && 
						notification.getNewStringValue().indexOf(":") != -1) {
					ActivityType feature = (ActivityType) notification
							.getNotifier();

					String resourceID = new String("");
					resourceType = new String("");

					String selectedResource = notification.getNewStringValue();

					resourceID = selectedResource.substring(0, selectedResource
							.indexOf(":"));
					resourceType = selectedResource.substring(selectedResource
							.indexOf(":") + 1);

					// feature.setInstanceName("Select a new Activity");
					feature.setName(resourceType);
					feature.setResource(resourceID);
				} else if (notification.getNewStringValue() == null ||
						notification.getNewStringValue().length() == 0 || 
						notification.getNewStringValue() == "") {
					ActivityType feature = (ActivityType) notification
							.getNotifier();
					feature.setName("Select a new DRR Activity");

				}

			}
		}
	};

	/**
	 * This constructs an instance from a factory and a notifier. <!--
	 * begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public ActivityTypeItemProvider(AdapterFactory adapterFactory) {
		super(adapterFactory);
	}

	private String getServerURL(Object object) {
		ResourceSet rs = ((EObject) object).eResource().getResourceSet();
		/**
		 * The GMFResourceImpl is loaded as first resource. TODO check if is
		 * always true
		 */
		Resource r = rs.getResources().get(0);

		String serverURL = ServerClient.DEFAULT_URL;

		PropertiesStyle style = null;
		/**
		 * Iterates through all the objects contained in the resource.
		 */
		for (TreeIterator<EObject> i = r.getAllContents(); i.hasNext();) {
			EObject obj = i.next();
			if (obj instanceof PropertiesStyle) {
				style = (PropertiesStyle) obj;
				if (style != null && style.getServerURL().length() > 0) {
					System.out.println("Server URL " + style.getServerURL());
					serverURL = style.getServerURL();
					break;
				}
			}
		}
		return serverURL;
	}

	/**
	 * This returns the property descriptors for the adapted class. <!--
	 * begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@Override
	public List<IItemPropertyDescriptor> getPropertyDescriptors(Object object) {
		if (itemPropertyDescriptors == null) {
			super.getPropertyDescriptors(object);

			addInstanceNamePropertyDescriptor(object);
			addNamePropertyDescriptor(object);
			addResourcePropertyDescriptor(object);
		}
		return itemPropertyDescriptors;
	}

	/**
	 * This adds a property descriptor for the Instance Name feature. <!--
	 * begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	protected void addInstanceNamePropertyDescriptor(Object object) {
		itemPropertyDescriptors.add
			(createItemPropertyDescriptor
				(((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory(),
				 getResourceLocator(),
				 getString("_UI_ActivityType_instanceName_feature"),
				 getString("_UI_PropertyDescriptor_description", "_UI_ActivityType_instanceName_feature", "_UI_ActivityType_type"),
				 ModelPackage.Literals.ACTIVITY_TYPE__INSTANCE_NAME,
				 true,
				 false,
				 false,
				 ItemPropertyDescriptor.GENERIC_VALUE_IMAGE,
				 null,
				 null));
	}

	/**
	 * This adds a property descriptor for the Name feature. <!-- begin-user-doc
	 * --> <!-- end-user-doc -->
	 * 
	 * @generated NOT
	 */
	protected void addNamePropertyDescriptor(Object object) {
		itemPropertyDescriptors.add(new ItemPropertyDescriptor(
				((ComposeableAdapterFactory) adapterFactory)
						.getRootAdapterFactory(), getResourceLocator(),
				getString("_UI_ActivityType_name_feature"), getString(
						"_UI_PropertyDescriptor_description",
						"_UI_ActivityType_name_feature",
						"_UI_ActivityType_type"),
				ModelPackage.Literals.ACTIVITY_TYPE__NAME, true, false, true,
				ItemPropertyDescriptor.GENERIC_VALUE_IMAGE, null, null) {
			public Collection getChoiceOfValues(Object object) {

				Collection activities = new ArrayList();

				/**
				 * Gets the resource that is associated with the Activity. If
				 * the value is "" no resource is associated to the activity
				 */
				String selectedResource = ((ActivityType) object).getResource();
				resourceType = ((ActivityType) object).getName();
				/**
				 * If no resource is selected the server queried in order to get
				 * the default list of instances. When is not possible to reach
				 * the server an error msg is returned. If there is a resource
				 * selected the instance relative to the parlicular resource are
				 * returned.
				 */
				if (selectedResource == null || selectedResource.length() == 0
						|| selectedResource == "") {
					try {
						ServerClient client = new ServerClient(getServerURL(object));
						activities = client.listResoucreDefaultActivity();
					} catch (MalformedURLException e) {
						activities.add("Unable to connect to the server");
					} catch (Exception e) {
						e.printStackTrace();
					}
				} else {
					try {

						String resourceID = selectedResource;

						ServerClient client = new ServerClient(getServerURL(object));
						activities = client.listResourceActivity(resourceID,
								resourceType);

					} catch (ResourceUnknownException e) {
						activities.add("The resource " + e.getResourceID()
								+ " is unknown.");
					} catch (MalformedURLException e) {						
						activities.add(new String(
								"Unable to connect to the server"));
					}  catch (Exception e) {						
						activities.add(new String(
						"Unable to connect to the server"));
					}
				}

				return activities;
			}
		});
	}

	/**
	 * This adds a property descriptor for the Resource feature. <!--
	 * begin-user-doc --> This methods will query the OGSA-DAI in order to get
	 * the list of resources that can be associated with the Activity. The
	 * server URL is stored in a notational style class, serialized with the GMF
	 * diagram. <!-- end-user-doc -->
	 * 
	 * @generated NOT
	 */
	protected void addResourcePropertyDescriptor(Object object) {
		itemPropertyDescriptors.add(new ItemPropertyDescriptor(
				((ComposeableAdapterFactory) adapterFactory)
						.getRootAdapterFactory(), getResourceLocator(),
				getString("_UI_ActivityType_resource_feature"), getString(
						"_UI_PropertyDescriptor_description",
						"_UI_ActivityType_resource_feature",
						"_UI_ActivityType_type"),
				ModelPackage.Literals.ACTIVITY_TYPE__RESOURCE, true, false,
				true, ItemPropertyDescriptor.GENERIC_VALUE_IMAGE, null, null) {
			public Collection getChoiceOfValues(Object object) {

				Collection resources = new ArrayList();
				try {

					ServerClient client = new ServerClient(getServerURL(object));
					resources = client.listResoucesAll();
					/**
					 * Add an empty line in order to not associate any resource
					 * with the selected activity
					 */
					resources.add(new String(""));
				} catch (Exception e) {
					e.printStackTrace();
					resources = new ArrayList();
					resources
							.add(new String("Unable to connect to the server"));
				}

				return resources;
			}
		});
	}

	/**
	 * This specifies how to implement {@link #getChildren} and is used to deduce an appropriate feature for an
	 * {@link org.eclipse.emf.edit.command.AddCommand}, {@link org.eclipse.emf.edit.command.RemoveCommand} or
	 * {@link org.eclipse.emf.edit.command.MoveCommand} in {@link #createCommand}.
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Collection<? extends EStructuralFeature> getChildrenFeatures(
			Object object) {
		if (childrenFeatures == null) {
			super.getChildrenFeatures(object);
			childrenFeatures.add(ModelPackage.Literals.ACTIVITY_TYPE__INPUTS);
			childrenFeatures.add(ModelPackage.Literals.ACTIVITY_TYPE__OUTPUTS);
		}
		return childrenFeatures;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	protected EStructuralFeature getChildFeature(Object object, Object child) {
		// Check the type of the specified child object and return the proper feature to use for
		// adding (see {@link AddCommand}) it as a child.

		return super.getChildFeature(object, child);
	}

	/**
	 * This returns ActivityType.gif. <!-- begin-user-doc --> <!-- end-user-doc
	 * -->
	 * 
	 * @generated
	 */
	@Override
	public Object getImage(Object object) {
		return overlayImage(object, getResourceLocator().getImage("full/obj16/ActivityType"));
	}

	/**
	 * This returns the label text for the adapted class. <!-- begin-user-doc
	 * --> <!-- end-user-doc -->
	 * 
	 * @generated NOT
	 */
	@Override
	public String getText(Object object) {
		((ActivityType) object).eAdapters().add(resourceAdapter);
		String label = ((ActivityType) object).getName();
		return label == null || label.length() == 0 ? getString("_UI_ActivityType_type")
				: getString("_UI_ActivityType_type") + " " + label;
	}

	/**
	 * This handles model notifications by calling {@link #updateChildren} to update any cached
	 * children and by creating a viewer notification, which it passes to {@link #fireNotifyChanged}.
	 * <!-- begin-user-doc --> <!--
	 * end-user-doc -->
	 * @generated
	 */
	@Override
	public void notifyChanged(Notification notification) {
		updateChildren(notification);

		switch (notification.getFeatureID(ActivityType.class)) {
			case ModelPackage.ACTIVITY_TYPE__INSTANCE_NAME:
			case ModelPackage.ACTIVITY_TYPE__NAME:
			case ModelPackage.ACTIVITY_TYPE__RESOURCE:
				fireNotifyChanged(new ViewerNotification(notification, notification.getNotifier(), false, true));
				return;
			case ModelPackage.ACTIVITY_TYPE__INPUTS:
			case ModelPackage.ACTIVITY_TYPE__OUTPUTS:
				fireNotifyChanged(new ViewerNotification(notification, notification.getNotifier(), true, false));
				return;
		}
		super.notifyChanged(notification);
	}

	/**
	 * This adds {@link org.eclipse.emf.edit.command.CommandParameter}s
	 * describing the children that can be created under this object. <!--
	 * begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@Override
	protected void collectNewChildDescriptors(
			Collection<Object> newChildDescriptors, Object object) {
		super.collectNewChildDescriptors(newChildDescriptors, object);

		newChildDescriptors.add
			(createChildParameter
				(ModelPackage.Literals.ACTIVITY_TYPE__INPUTS,
				 ModelFactory.eINSTANCE.createInputsType()));

		newChildDescriptors.add
			(createChildParameter
				(ModelPackage.Literals.ACTIVITY_TYPE__OUTPUTS,
				 ModelFactory.eINSTANCE.createOutputsType()));
	}

	/**
	 * Return the resource locator for this item provider's resources. <!--
	 * begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@Override
	public ResourceLocator getResourceLocator() {
		return RequestEditPlugin.INSTANCE;
	}

}